<script lang="ts" setup>
import { ref, onMounted, computed, watchEffect, reactive, nextTick } from "vue"
import type { FormInstance } from 'element-plus'
import { useRouter } from 'vue-router';
import { useAuthStore } from '#/store';
import { PASSWORD, VERIFICATION_CODE } from "#/utils/constants"
import Code from "#/components/common/code.vue"
import setPublicCode from "#/utils/setPublicKey"
import { TelMatcher } from "#/utils/constants"
import { $t } from '@vben/locales';
import { getVoiceVerificationOpenCodeApi, getVerificationOpenCodeApi } from "#/api/core/auth"
import { useCodeName } from "#/hooks/useCodeName"
import SliderDialog from "#/components/slider-dialog.vue"

defineOptions({ name: 'Login' });

const { isVoiceCode, codeBtnName, codeInputPlaceholder } = useCodeName()
const authStore = useAuthStore();
const router = useRouter();
const formRef = ref<FormInstance>()
const passwordInputKey = ref(0)
const isCodeSwitching = ref(false)
const activeTab = ref<string>(PASSWORD);
const codeRef = ref<any>(null);
const isPassword = computed(() => activeTab.value === PASSWORD)
const isVerificationCode = computed(() => activeTab.value === VERIFICATION_CODE)

// 使用统一的表单数据，但在验证码类型切换时不直接操作它
const ruleForm = ref({
  phoneNumber: "",
  verificationCode: '',
  password: ""
})
// 状态变量
const sliderDialogVisible = ref(false);
const sliderDialogRef = ref<any>(null);
let codeCallBack: Function | null = null;
// 在 tab 切换时清理不相关字段
watchEffect(() => {
  // 切换 tab 时临时禁用校验
  isCodeSwitching.value = true

  if (isPassword.value) {
    ruleForm.value.verificationCode = ''
  } else {
    ruleForm.value.password = ''
  }

  // 延长切换状态，确保所有异步操作完成
  setTimeout(() => {
    isCodeSwitching.value = false
  }, 100)
})

const rules = reactive({
  phoneNumber: [
    { required: true, pattern: TelMatcher, message: $t('common.phonePhTxt'), trigger: 'blur' },
  ],
  verificationCode: [
    {
      required: true,
      message: codeInputPlaceholder,
      trigger: 'blur',
      validator: (rule: any, value: any, callback: any) => {
        // 如果正在切换验证码类型，跳过校验
        if (isCodeSwitching.value) {
          callback()
          return
        }
        // 正常校验
        if (!value) {
          callback(new Error(codeInputPlaceholder.value))
        } else {
          callback()
        }
      }
    },
  ],
  password: [
    { required: true, message: $t('common.inputPhTxt', [$t('login.password')]), trigger: 'blur' },
  ]
})

// 登录成功后需要判断用户身份，是跳转到客户端还是服务端
const sumbit = (e: any) => {
  if (!formRef) return
  if (e?.key === 'Enter') {
    e.preventDefault();
  }
  formRef.value?.validate((valid) => {
    if (valid) {
      authStore.authLogin({
        type: activeTab.value,
        ...ruleForm.value,
        password: isPassword.value ? setPublicCode(ruleForm.value.password) : ''
      }).then(res => {
      }).finally(() => {
        authStore.$reset()
      })
    }
  })
}

const onRegister = () => {
  router.push('/auth/register')
}

const onResetPassword = () => {
  router.push('/auth/resetPassword')
}

//获取验证码
const getCode = (callback: Function) => {
  formRef.value?.validateField(['phoneNumber'], (valid) => {
    if (valid) {
      sliderDialogVisible.value = true
      codeCallBack = callback;
    }
  })
}

const isSumbit = computed(() => {
  if (
    ruleForm.value.phoneNumber &&
    ((isPassword && ruleForm.value.password) ||
      (isVerificationCode && ruleForm.value.verificationCode))
  ) return false
  return true
})

function getTextWidth(text: string): number {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d')!;
  context.font = '16px sans-serif'; // 假设字体大小为 16px
  return context.measureText(text).width * 0.5; // 取约 2 个字体宽度
}

const switchTab = (tab: string) => {
  activeTab.value = tab;

  // 重置表单数据
  ruleForm.value = {
    phoneNumber: "",
    verificationCode: '',
    password: ""
  }
};
const underlineStyle = computed(() => ({
  // 下划线宽度：约两个字体长度（动态计算）
  width: `${getTextWidth(activeTab.value === PASSWORD ? $t('login.passwordLogin') : $t('login.smsLogin'))}px`,
  // 下划线距离文字底部 5px
  bottom: '-5px',
}));

onMounted(() => {
  formRef.value?.resetFields()

  // 强化的密码防自动填充措施
  setTimeout(() => {
    const inputs = document.querySelectorAll('input[type="text"], input[type="password"]')
    inputs.forEach((input: any) => {
      // 清除页面加载时的自动填充值
      if (input.value && input.value.length > 0 &&
        !ruleForm.value.phoneNumber &&
        !ruleForm.value.password &&
        !ruleForm.value.verificationCode) {
        input.value = ''
      }

      // 添加防自动填充属性
      input.setAttribute('data-lpignore', 'true')
      input.setAttribute('data-1p-ignore', 'true')

      // 专门处理密码输入框
      if (input.type === 'password') {
        // 监听值变化，防止程序化填充
        const observer = new MutationObserver((mutations) => {
          mutations.forEach((mutation) => {
            if (mutation.type === 'attributes' && mutation.attributeName === 'value') {
              // 检测到值被程序化修改，可能是自动填充
              if (input.value && !ruleForm.value.password) {
                input.value = ''
              }
            }
          })
        })

        observer.observe(input, {
          attributes: true,
          attributeFilter: ['value']
        })
      }
    })

    // 定期检查密码输入框，防止延迟自动填充
    const passwordCheckInterval = setInterval(() => {
      const passwordInputs = document.querySelectorAll('input[type="password"]')
      passwordInputs.forEach((input: any) => {
        // 只清除明显的自动填充（长度大于8且Vue数据为空的情况）
        if (input.value && input.value.length > 8 && !ruleForm.value.password) {
          console.log('检测到可能的自动填充密码，已清除')
          input.value = ''
          // 强制重渲染密码组件
          passwordInputKey.value++
        }
      })
    }, 2000)

    // 3秒后停止检查
    setTimeout(() => {
      clearInterval(passwordCheckInterval)
    }, 3000)
  }, 200)
})

const getVoiceCode = (value: boolean) => {
  if (codeRef.value.isCounting) return;
  // 设置切换状态，禁用校验
  isCodeSwitching.value = true
  isVoiceCode.value = value
  ruleForm.value.verificationCode = ''
  // 延长切换状态，确保所有异步操作完成
  setTimeout(() => {
    isCodeSwitching.value = false
  }, 100)
}

// 处理密码框焦点事件，防止自动填充
const handlePasswordFocus = () => {
  // 检查并清除可能的自动填充
  setTimeout(() => {
    // 只清除明显的自动填充（长度大于10的预填充值）
    const passwordInput = document.querySelector('input[type="password"]') as HTMLInputElement
    if (passwordInput && passwordInput.value &&
      !ruleForm.value.password &&
      passwordInput.value.length > 10) {
      // 清除自动填充的值
      passwordInput.value = ''
      ruleForm.value.password = ''
      // 重新生成组件key，强制重渲染
      passwordInputKey.value++
    }
  }, 100)
}

// 处理密码框粘贴事件
const handlePasswordPaste = (event: ClipboardEvent) => {
  // 允许粘贴，但验证粘贴的内容
  setTimeout(() => {
    const target = event.target as HTMLInputElement
    if (target.value !== ruleForm.value.password) {
      ruleForm.value.password = target.value
    }
  }, 10)
}

// 登录页面验证码输入框焦点处理
const handleLoginCodeFocus = () => {
  // 验证码获得焦点时清除任何可能的自动填充
  setTimeout(() => {
    if (ruleForm.value.verificationCode && ruleForm.value.verificationCode.length > 6) {
      // 清除可能的错误自动填充（验证码通常不超过6位）
      ruleForm.value.verificationCode = ''
    }
  }, 50)
}
// 登录页面验证码输入处理
const handleLoginCodeInput = (value: string) => {
  // 只允许数字输入
  const numericValue = value.replace(/[^0-9]/g, '')
  if (numericValue !== value) {
    ruleForm.value.verificationCode = numericValue
  }
  // 限制长度
  if (numericValue.length > 10) {
    ruleForm.value.verificationCode = numericValue.slice(0, 10)
  }
}
const handleVerifySuccess = async (data: string) => {
  try {
    codeCallBack?.();
    if (isVoiceCode.value) {
      await getVoiceVerificationOpenCodeApi({ phoneNumber: ruleForm.value.phoneNumber, captchaKey: data })
    } else {
      await getVerificationOpenCodeApi({ phoneNumber: ruleForm.value.phoneNumber, captchaKey: data })
    }
  } catch (error) {
    console.error('验证失败:', error);
  }
}

</script>
<template>
  <!-- 登录 -->
  <div class="login flex flex-col items-center overflow-auto" style="box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.16);">
    <div class="px-[56px] w-full">
      <div class="pb-[36px] font-semibold text-[26px] pt-[49px] w-full text-[#191919]">{{ $t('login.loginName') }}</div>
      <div class="tabs-container pb-[24px]">
        <button key="password" class="tab-button" :class="{ 'tab-active': activeTab === PASSWORD }"
          @click="switchTab(PASSWORD)">
          {{ $t('login.passwordLogin') }}
          <span class="underline" :style="underlineStyle"></span>
        </button>
        <button key="sms" class="tab-button pl-[15px]" :class="{ 'tab-active': activeTab === VERIFICATION_CODE }"
          @click="switchTab(VERIFICATION_CODE)">
          {{ $t('login.smsLogin') }}
          <span class="underline" :style="underlineStyle"></span>
        </button>
      </div>
      <el-form ref="formRef" class="w-[100%] text-right" :model="ruleForm" :rules="rules" label-position="left"
        autocomplete="off" data-lpignore="true" data-1p-ignore="true" @keyup.enter="sumbit">
        <!-- 隐藏的假输入框来误导浏览器 -->
        <input type="text" style="position: absolute; left: -9999px; width: 1px; height: 1px;" name="username"
          autocomplete="username" tabindex="-1" value="" />
        <input type="password" style="position: absolute; left: -9999px; width: 1px; height: 1px;" name="password"
          autocomplete="current-password" tabindex="-1" value="" />
        <input type="email" style="position: absolute; left: -9999px; width: 1px; height: 1px;" name="email"
          autocomplete="email" tabindex="-1" value="" />
        <input type="text" style="position: absolute; left: -9999px; width: 1px; height: 1px;" name="search_field"
          autocomplete="off" tabindex="-1" value="" />

        <el-form-item label="" prop="phoneNumber" style="margin-bottom: 30px !important;">
          <el-input v-model="ruleForm.phoneNumber" size="large" maxlength="11"
            :placeholder="$t('common.inputPhTxt', [$t('common.phoneTxt')])" autocomplete="nope"
            name="disable-autofill-phone" data-lpignore="true" data-1p-ignore="true" data-form-type="other"
            :readonly="false" />
        </el-form-item>
        <!-- 语言和短信验证码 -->
        <el-form-item label="" :prop="isCodeSwitching ? '' : 'verificationCode'" v-if="isVerificationCode">
          <el-input v-model="ruleForm.verificationCode" size="large" minlength="3" maxlength="10"
            :placeholder="codeInputPlaceholder" autocomplete="one-time-code"
            :name="`login-verification-code-${Date.now()}`" data-lpignore="true" data-1p-ignore="true"
            data-form-type="verification" inputmode="numeric" pattern="[0-9]*" spellcheck="false"
            @focus="handleLoginCodeFocus" @input="handleLoginCodeInput" :readonly="false">
            <template #append>
              <Code @getCode="getCode" :authCode="ruleForm.phoneNumber" :codeName="codeBtnName" ref="codeRef"></Code>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item label="" prop="password" v-if="isPassword">
          <el-input v-model="ruleForm.password" size="large" minlength="6" maxlength="20" type="password" show-password
            :placeholder="$t('common.inputPhTxt', [$t('login.password')])" autocomplete="off"
            :name="`secure-pwd-${Math.random().toString(36).substring(2, 15)}`" data-lpignore="true"
            data-1p-ignore="true" data-form-type="search" data-testid="custom-password-field"
            @focus="handlePasswordFocus" @paste="handlePasswordPaste" :key="passwordInputKey" />
        </el-form-item>
        <p class="cursor-pointer text-[12px] text-[#909399] h-[10px]">
          <span v-if="isPassword" @click="onResetPassword">{{ $t('login.forgetPassword') }}</span>
        </p>
        <!-- 语音验证码 -->
        <p v-if="isVerificationCode && ruleForm.phoneNumber" class="text-[12px] text-[#909399] h-[10px]">
          <template v-if="!isVoiceCode">
            {{ $t('login.noSmsCode') }}<span class="text-[#0067D1] cursor-pointer" @click="getVoiceCode(true)">
              {{ $t('login.voiceLogin') }}</span>
          </template>
          <template v-else>
            <span class="text-[#0067D1] cursor-pointer" @click="getVoiceCode(false)">{{
              $t('login.switchSmsCode') }}</span>
          </template>
        </p>
      </el-form>
      <div class="sumbit pt-[25px] pb-[43px] w-[100%]">
        <el-button type="primary" size="large" class="w-[100%]" :disabled="isSumbit" @click="sumbit"
          :loading="authStore.loginLoading">
          {{ $t('login.loginButton') }}
        </el-button>
      </div>
    </div>
    <div class="h-[56px] bg-[#F2F7FD] w-full flex items-center justify-center">
      <small>{{ $t('login.noAccountText') }}</small>
      <el-button link type="primary" @click="onRegister">{{ $t('login.registerNow') }}</el-button>
    </div>
    <SliderDialog v-model:visible="sliderDialogVisible" ref="sliderDialogRef" :phone="ruleForm.phoneNumber"
      @verify-success="handleVerifySuccess" />
  </div>
</template>
<style lang="less" scoped>
.color-text {
  @apply text-[#191919];
}

.tabs-container {
  @apply flex items-end space-x-4 w-full;
}

.tab-button {
  @apply py-2 text-base cursor-pointer transition-colors duration-300 relative;
  color: black;
  .color-text;
  font-size: 20px;
  /* 未选中时的颜色 */
}

.tab-active {
  @apply text-[#0067D1];
}

/* 下划线样式 */
.underline {
  position: absolute;
  left: 50%;
  height: 2px;
  background-color: var(--el-color-primary);
  transition: all 0.3s ease;
  transform: translateX(-50%) scaleX(0);
}

/* 过渡动画 */
.tab-fade-enter-active,
.tab-fade-leave-active {
  @apply transition-all duration-300;
}

.tab-fade-enter-from {
  @apply opacity-0 translate-y-2;
}

.tab-fade-leave-to {
  @apply opacity-0 translate-y-2;
}

/* 激活时下划线展开 */
.tab-active .underline {
  transform: translateX(-50%) scaleX(1);
}
</style>
